#include <accent/algorithms/rotate.hpp>
#include <accent/algorithms/filter.hpp>
#include "test_base.hpp"

template <typename Traversal>
class FilteredRotate : public ::testing::Test {};

typedef ::testing::Types<forward_traversal_tag, bidirectional_traversal_tag>
  traversals;
TYPED_TEST_CASE(FilteredRotate, traversals);

template <typename Traversal, typename Container>
auto filtercp(Container& c)
  -> decltype(limit_traversal<Traversal>(filter(all(c), positive())))
{
  return limit_traversal<Traversal>(filter(all(c), positive()));
}

TYPED_TEST(FilteredRotate, rotateZero)
{
  ivec v = { 1, -1, 2, -2, 3, -3, 4, -4 },
       e = { 1, -1, 2, -2, 3, -3, 4, -4 };
  auto r = filtercp<TypeParam>(v), s = r;
  auto p = rotate(r, s.front_position());
  ASSERT_EQ(e, v);
  ASSERT_FALSE(!p);
  ASSERT_EQ(1, *p);
}

TYPED_TEST(FilteredRotate, rotateOne)
{
  ivec v = { 1, -1, 2, -2, 3, -3, 4, -4 },
       e = { 2, -1, 3, -2, 4, -3, 1, -4 };
  auto r = filtercp<TypeParam>(v), s = r;
  s.pop_front();
  auto p = rotate(r, s.front_position());
  ASSERT_EQ(e, v);
  ASSERT_FALSE(!p);
  ASSERT_EQ(1, *p);
}

TYPED_TEST(FilteredRotate, rotateTwo)
{
  ivec v = { 1, -1, 2, -2, 3, -3, 4, -4 },
       e = { 3, -1, 4, -2, 1, -3, 2, -4 };
  auto r = filtercp<TypeParam>(v), s = r;
  s.pop_front();
  s.pop_front();
  auto p = rotate(r, s.front_position());
  ASSERT_EQ(e, v);
  ASSERT_FALSE(!p);
  ASSERT_EQ(1, *p);
}

TYPED_TEST(FilteredRotate, rotateThree)
{
  ivec v = { 1, -1, 2, -2, 3, -3, 4, -4 },
       e = { 4, -1, 1, -2, 2, -3, 3, -4 };
  auto r = filtercp<TypeParam>(v), s = r;
  s.pop_front();
  s.pop_front();
  s.pop_front();
  auto p = rotate(r, s.front_position());
  ASSERT_EQ(e, v);
  ASSERT_FALSE(!p);
  ASSERT_EQ(1, *p);
}
